/*!
 * \file UftStraBaseCtx.h
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief UFT策略基础上下文定义文件
 * 
 * \details 定义了UFT(Ultra Fast Trading)策略基础上下文类，为UFT策略提供完整的
 *          交易和数据访问接口。该类继承自IUftStraCtx和ITrdNotifySink，提供策略
 *          执行所需的所有基础功能，包括交易下单、数据获取、持仓管理等。
 */
#pragma once

#include "../Includes/FasterDefs.h"
#include "../Includes/IUftStraCtx.h"
#include "../Share/BoostFile.hpp"
#include "../Share/fmtlib.h"

#include "ITrdNotifySink.h"

NS_WTP_BEGIN

class WtUftEngine;
class TraderAdapter;

/*!
 * \class UftStraBaseCtx
 * \brief UFT策略基础上下文类
 * 
 * \details UFT策略基础上下文，提供UFT策略运行所需的完整基础设施。
 *          主要功能包括：
 *          - 实现IUftStraCtx接口，提供策略交易和数据访问功能
 *          - 实现ITrdNotifySink接口，处理交易回报和通知
 *          - 管理与交易引擎和交易适配器的连接
 *          - 提供订单管理、持仓查询、数据订阅等核心功能
 *          - 支持多种订单类型（买入、卖出、开仓、平仓）
 *          - 提供Level2数据访问接口
 * 
 * \note 这是UFT策略的核心基类，所有具体的UFT策略上下文都继承自此类
 * \warning 所有交易接口都在高频环境下执行，需要确保极低延迟
 */
class UftStraBaseCtx : public IUftStraCtx, public ITrdNotifySink
{
public:
	/*!
	 * \brief 构造函数
	 * \param engine UFT引擎指针
	 * \param name 策略上下文名称
	 * 
	 * \details 初始化UFT策略基础上下文，建立与引擎的关联关系
	 */
	UftStraBaseCtx(WtUftEngine* engine, const char* name);
	
	/*!
	 * \brief 析构函数
	 * 
	 * \details 清理策略基础上下文资源，断开所有连接
	 */
	virtual ~UftStraBaseCtx();

	/*!
	 * \brief 设置交易适配器
	 * \param trader 交易适配器指针
	 * 
	 * \details 绑定交易适配器，用于处理实际的交易请求
	 */
	void setTrader(TraderAdapter* trader);

public:
	//////////////////////////////////////////////////////////////////////////
	// IUftStraCtx 接口实现
	
	/*!
	 * \brief 获取策略上下文ID
	 * \return uint32_t 上下文唯一标识
	 * 
	 * \details 返回策略上下文的唯一标识符，用于区分不同的策略实例
	 */
	virtual uint32_t id() override;

	/*!
	 * \brief 策略初始化回调
	 * 
	 * \details 策略启动时调用，进行初始化操作
	 */
	virtual void on_init() override;

	/*!
	 * \brief Tick数据回调
	 * \param stdCode 标准合约代码
	 * \param newTick 新的Tick数据
	 * 
	 * \details 接收实时Tick行情数据，这是UFT策略最重要的数据源
	 */
	virtual void on_tick(const char* stdCode, WTSTickData* newTick) override;

	/*!
	 * \brief 委托队列数据回调
	 * \param stdCode 标准合约代码
	 * \param newOrdQue 新的委托队列数据
	 * 
	 * \details 接收Level2委托队列数据，提供订单簿深度信息
	 */
	virtual void on_order_queue(const char* stdCode, WTSOrdQueData* newOrdQue) override;

	/*!
	 * \brief 委托明细数据回调
	 * \param stdCode 标准合约代码
	 * \param newOrdDtl 新的委托明细数据
	 * 
	 * \details 接收Level2委托明细数据，提供单笔委托详细信息
	 */
	virtual void on_order_detail(const char* stdCode, WTSOrdDtlData* newOrdDtl) override;

	/*!
	 * \brief 成交明细数据回调
	 * \param stdCode 标准合约代码
	 * \param newTrans 新的成交明细数据
	 * 
	 * \details 接收Level2成交明细数据，提供逐笔成交信息
	 */
	virtual void on_transaction(const char* stdCode, WTSTransData* newTrans) override;

	/*!
	 * \brief K线数据回调
	 * \param stdCode 标准合约代码
	 * \param period K线周期
	 * \param times 周期倍数
	 * \param newBar 新的K线数据
	 * 
	 * \details 接收K线数据更新，用于技术分析
	 */
	virtual void on_bar(const char* stdCode, const char* period, uint32_t times, WTSBarStruct* newBar) override;

	/*!
	 * \brief 获取当前交易日期
	 * \return uint32_t 交易日期（格式：YYYYMMDD）
	 */
	virtual uint32_t stra_get_date() override;
	
	/*!
	 * \brief 获取当前交易时间
	 * \return uint32_t 交易时间（格式：HHMM）
	 */
	virtual uint32_t stra_get_time() override;
	
	/*!
	 * \brief 获取当前精确时间（秒）
	 * \return uint32_t 精确时间（格式：HHMMSSsss）
	 */
	virtual uint32_t stra_get_secs() override;

	/*!
	 * \brief 撤销指定订单
	 * \param localid 本地订单ID
	 * \return bool 撤单请求是否成功提交
	 * 
	 * \details 撤销指定本地ID的订单，返回撤单请求是否成功提交
	 */
	virtual bool stra_cancel(uint32_t localid) override;

	/*!
	 * \brief 撤销指定合约的所有订单
	 * \param stdCode 标准合约代码
	 * \return OrderIDs 被撤销的订单ID列表
	 * 
	 * \details 撤销指定合约的所有未成交订单，返回被撤销的订单ID列表
	 */
	virtual OrderIDs stra_cancel_all(const char* stdCode) override;

	/*!
	 * \brief 买入下单接口
	 * \param stdCode 标准合约代码
	 * \param price 下单价格，0表示市价单
	 * \param qty 下单数量
	 * \param flag 下单标志：0-normal，1-fak，2-fok，默认0
	 * \return OrderIDs 订单ID列表
	 * 
	 * \details 提交买入订单，支持限价和市价两种方式。
	 *          flag参数说明：
	 *          - 0: 普通订单
	 *          - 1: FAK（Fill and Kill）立即成交剩余撤销
	 *          - 2: FOK（Fill or Kill）全部成交或全部撤销
	 */
	virtual OrderIDs	stra_buy(const char* stdCode, double price, double qty, int flag = 0) override;

	/*!
	 * \brief 卖出下单接口
	 * \param stdCode 标准合约代码
	 * \param price 下单价格，0表示市价单
	 * \param qty 下单数量
	 * \param flag 下单标志：0-normal，1-fak，2-fok，默认0
	 * \return OrderIDs 订单ID列表
	 * 
	 * \details 提交卖出订单，支持限价和市价两种方式。
	 *          flag参数说明同stra_buy方法
	 */
	virtual OrderIDs	stra_sell(const char* stdCode, double price, double qty, int flag = 0) override;

	/*!
	 * \brief 开多仓下单接口
	 * \param stdCode 标准合约代码
	 * \param price 下单价格，0表示市价单
	 * \param qty 下单数量
	 * \param flag 下单标志：0-normal，1-fak，2-fok
	 * \return uint32_t 本地订单ID
	 * 
	 * \details 开立多头持仓，适用于期货等有开平仓概念的合约
	 */
	virtual uint32_t	stra_enter_long(const char* stdCode, double price, double qty, int flag = 0) override;

	/*!
	 * \brief 开空仓下单接口
	 * \param stdCode 标准合约代码
	 * \param price 下单价格，0表示市价单
	 * \param qty 下单数量
	 * \param flag 下单标志：0-normal，1-fak，2-fok
	 * \return uint32_t 本地订单ID
	 * 
	 * \details 开立空头持仓，适用于期货等有开平仓概念的合约
	 */
	virtual uint32_t	stra_enter_short(const char* stdCode, double price, double qty, int flag = 0) override;

	/*!
	 * \brief 平多仓下单接口
	 * \param stdCode 标准合约代码
	 * \param price 下单价格，0表示市价单
	 * \param qty 下单数量
	 * \param isToday 是否平今仓，默认false
	 * \param flag 下单标志：0-normal，1-fak，2-fok，默认0
	 * \return uint32_t 本地订单ID
	 * 
	 * \details 平掉多头持仓，支持平今和平昨区分
	 */
	virtual uint32_t	stra_exit_long(const char* stdCode, double price, double qty, bool isToday = false, int flag = 0) override;

	/*!
	 * \brief 平空仓下单接口
	 * \param stdCode 标准合约代码
	 * \param price 下单价格，0表示市价单
	 * \param qty 下单数量
	 * \param isToday 是否平今仓，默认false
	 * \param flag 下单标志：0-normal，1-fak，2-fok，默认0
	 * \return uint32_t 本地订单ID
	 * 
	 * \details 平掉空头持仓，支持平今和平昨区分
	 */
	virtual uint32_t	stra_exit_short(const char* stdCode, double price, double qty, bool isToday = false, int flag = 0) override;

	/*!
	 * \brief 获取品种信息
	 * \param stdCode 标准合约代码
	 * \return WTSCommodityInfo* 品种信息指针
	 * 
	 * \details 获取指定合约的品种基础信息，包括最小变动价位、合约乘数等
	 */
	virtual WTSCommodityInfo* stra_get_comminfo(const char* stdCode) override;

	/*!
	 * \brief 获取K线数据
	 * \param stdCode 标准合约代码
	 * \param period K线周期
	 * \param count 获取K线数量
	 * \return WTSKlineSlice* K线数据切片
	 * 
	 * \details 获取指定合约的历史K线数据，用于技术分析
	 */
	virtual WTSKlineSlice* stra_get_bars(const char* stdCode, const char* period, uint32_t count) override;

	/*!
	 * \brief 获取Tick数据
	 * \param stdCode 标准合约代码
	 * \param count 获取Tick数量
	 * \return WTSTickSlice* Tick数据切片
	 * 
	 * \details 获取指定合约的历史Tick数据
	 */
	virtual WTSTickSlice* stra_get_ticks(const char* stdCode, uint32_t count) override;

	/*!
	 * \brief 获取委托明细数据
	 * \param stdCode 标准合约代码
	 * \param count 获取数据数量
	 * \return WTSOrdDtlSlice* 委托明细数据切片
	 * 
	 * \details 获取指定合约的Level2委托明细历史数据
	 */
	virtual WTSOrdDtlSlice*	stra_get_order_detail(const char* stdCode, uint32_t count) override;

	/*!
	 * \brief 获取委托队列数据
	 * \param stdCode 标准合约代码
	 * \param count 获取数据数量
	 * \return WTSOrdQueSlice* 委托队列数据切片
	 * 
	 * \details 获取指定合约的Level2委托队列历史数据
	 */
	virtual WTSOrdQueSlice*	stra_get_order_queue(const char* stdCode, uint32_t count) override;

	/*!
	 * \brief 获取成交明细数据
	 * \param stdCode 标准合约代码
	 * \param count 获取数据数量
	 * \return WTSTransSlice* 成交明细数据切片
	 * 
	 * \details 获取指定合约的Level2成交明细历史数据
	 */
	virtual WTSTransSlice*	stra_get_transaction(const char* stdCode, uint32_t count) override;

	/*!
	 * \brief 获取最新Tick数据
	 * \param stdCode 标准合约代码
	 * \return WTSTickData* 最新Tick数据指针
	 * 
	 * \details 获取指定合约的最新Tick数据
	 */
	virtual WTSTickData* stra_get_last_tick(const char* stdCode) override;

	/*!
	 * \brief 输出信息级别日志
	 * \param message 日志消息
	 * 
	 * \details 输出信息级别的策略日志
	 */
	virtual void stra_log_info(const char* message) override;
	
	/*!
	 * \brief 输出调试级别日志
	 * \param message 日志消息
	 * 
	 * \details 输出调试级别的策略日志
	 */
	virtual void stra_log_debug(const char* message) override;
	
	/*!
	 * \brief 输出错误级别日志
	 * \param message 日志消息
	 * 
	 * \details 输出错误级别的策略日志
	 */
	virtual void stra_log_error(const char* message) override;

	/*!
	 * \brief 获取持仓数量
	 * \param stdCode 标准合约代码
	 * \param bOnlyValid 是否只获取有效持仓，默认false
	 * \param iFlag 持仓标志，默认3（多空合计）
	 * \return double 持仓数量
	 * 
	 * \details 获取指定合约的持仓数量，支持多种查询模式
	 */
	virtual double stra_get_position(const char* stdCode, bool bOnlyValid = false, int32_t iFlag = 3) override;
	
	/*!
	 * \brief 枚举持仓
	 * \param stdCode 标准合约代码
	 * \return double 持仓数量
	 * 
	 * \details 枚举指定合约的持仓信息
	 */
	virtual double stra_enum_position(const char* stdCode) override;
	
	/*!
	 * \brief 获取最新价格
	 * \param stdCode 标准合约代码
	 * \return double 最新价格
	 * 
	 * \details 获取指定合约的最新价格
	 */
	virtual double stra_get_price(const char* stdCode) override;
	
	/*!
	 * \brief 获取未完成订单数量
	 * \param stdCode 标准合约代码
	 * \return double 未完成订单数量
	 * 
	 * \details 获取指定合约的未完成订单总数量
	 */
	virtual double stra_get_undone(const char* stdCode) override;

	/*!
	 * \brief 订阅Tick数据
	 * \param stdCode 标准合约代码
	 * 
	 * \details 订阅指定合约的Tick数据推送
	 */
	virtual void stra_sub_ticks(const char* stdCode) override;
	
	/*!
	 * \brief 订阅委托明细数据
	 * \param stdCode 标准合约代码
	 * 
	 * \details 订阅指定合约的Level2委托明细数据推送
	 */
	virtual void stra_sub_order_details(const char* stdCode) override;
	
	/*!
	 * \brief 订阅委托队列数据
	 * \param stdCode 标准合约代码
	 * 
	 * \details 订阅指定合约的Level2委托队列数据推送
	 */
	virtual void stra_sub_order_queues(const char* stdCode) override;
	
	/*!
	 * \brief 订阅成交明细数据
	 * \param stdCode 标准合约代码
	 * 
	 * \details 订阅指定合约的Level2成交明细数据推送
	 */
	virtual void stra_sub_transactions(const char* stdCode) override;

	//////////////////////////////////////////////////////////////////////////
	// ITrdNotifySink 接口实现
	
	/*!
	 * \brief 成交回报通知
	 * \param localid 本地订单ID
	 * \param stdCode 标准合约代码
	 * \param isLong 是否多头方向
	 * \param offset 开平仓标志
	 * \param vol 成交数量
	 * \param price 成交价格
	 * 
	 * \details 接收交易成交通知，更新策略的持仓和风险状态
	 */
	virtual void on_trade(uint32_t localid, const char* stdCode, bool isLong, uint32_t offset, double vol, double price) override;

	/*!
	 * \brief 订单状态通知
	 * \param localid 本地订单ID
	 * \param stdCode 标准合约代码
	 * \param isLong 是否多头方向
	 * \param offset 开平仓标志
	 * \param totalQty 订单总量
	 * \param leftQty 剩余数量
	 * \param price 订单价格
	 * \param isCanceled 是否已撤销
	 * 
	 * \details 接收订单状态变化通知，跟踪订单生命周期
	 */
	virtual void on_order(uint32_t localid, const char* stdCode, bool isLong, uint32_t offset, double totalQty, double leftQty, double price, bool isCanceled) override;

	/*!
	 * \brief 交易通道就绪通知
	 * 
	 * \details 交易通道连接成功并就绪时触发
	 */
	virtual void on_channel_ready() override;

	/*!
	 * \brief 交易通道断开通知
	 * 
	 * \details 交易通道连接断开时触发
	 */
	virtual void on_channel_lost() override;

	/*!
	 * \brief 委托结果通知
	 * \param localid 本地订单ID
	 * \param stdCode 标准合约代码
	 * \param bSuccess 委托是否成功
	 * \param message 错误信息（如果失败）
	 * 
	 * \details 接收订单提交结果通知
	 */
	virtual void on_entrust(uint32_t localid, const char* stdCode, bool bSuccess, const char* message) override;

	/*!
	 * \brief 持仓变化通知
	 * \param stdCode 标准合约代码
	 * \param isLong 是否多头持仓
	 * \param prevol 昨仓数量
	 * \param preavail 昨仓可用数量
	 * \param newvol 今仓数量
	 * \param newavail 今仓可用数量
	 * \param tradingday 交易日
	 * 
	 * \details 接收持仓变化通知，更新策略的持仓状态
	 */
	virtual void on_position(const char* stdCode, bool isLong, double prevol, double preavail, double newvol, double newavail, uint32_t tradingday) override;

private:
	/*!
	 * \brief 调试日志模板方法
	 * \tparam Args 参数类型包
	 * \param format 格式化字符串
	 * \param args 格式化参数
	 * 
	 * \details 提供格式化的调试日志输出功能
	 */
	template<typename... Args>
	void log_debug(const char* format, const Args& ...args)
	{
		std::string s = fmt::sprintf(format, args...);
		stra_log_debug(s.c_str());
	}

	/*!
	 * \brief 信息日志模板方法
	 * \tparam Args 参数类型包
	 * \param format 格式化字符串
	 * \param args 格式化参数
	 * 
	 * \details 提供格式化的信息日志输出功能
	 */
	template<typename... Args>
	void log_info(const char* format, const Args& ...args)
	{
		std::string s = fmt::sprintf(format, args...);
		stra_log_info(s.c_str());
	}

	/*!
	 * \brief 错误日志模板方法
	 * \tparam Args 参数类型包
	 * \param format 格式化字符串
	 * \param args 格式化参数
	 * 
	 * \details 提供格式化的错误日志输出功能
	 */
	template<typename... Args>
	void log_error(const char* format, const Args& ...args)
	{
		std::string s = fmt::sprintf(format, args...);
		stra_log_error(s.c_str());
	}

protected:
	/*!
	 * \brief 获取订单标签
	 * \param localid 本地订单ID
	 * \return const char* 订单标签字符串
	 * 
	 * \details 根据本地订单ID获取对应的订单标签
	 */
	inline const char* getOrderTag(uint32_t localid)
	{
		auto it = _orders.find(localid);
		if (it == _orders.end())
			return "";

		return it->second.c_str();
	}


protected:
	uint32_t		_context_id;	///< 策略上下文ID
	WtUftEngine*	_engine;		///< UFT引擎指针
	TraderAdapter*	_trader;		///< 交易适配器指针

private:
	typedef faster_hashmap<uint32_t, std::string> OrderMap;	///< 订单映射表类型定义
	OrderMap		_orders;		///< 订单标签映射表，键为本地订单ID，值为订单标签
};

NS_WTP_END
